package com.cloudweb.oa.utils;

import com.cloudwebsoft.framework.util.LogUtil;
import com.itextpdf.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfDocument;
import org.apache.commons.io.FileUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream;
import org.ofdrw.converter.ConvertHelper;
import org.ofdrw.converter.GeneralConvertException;
//import org.ofdrw.converter.SVGMaker;
import org.ofdrw.converter.SVGMaker;
import org.ofdrw.converter.export.HTMLExporter;
import org.ofdrw.converter.export.ImageExporter;
import org.ofdrw.converter.export.TextExporter;
import org.ofdrw.converter.ofdconverter.ImageConverter;
import org.ofdrw.converter.ofdconverter.PDFConverter;
import org.ofdrw.converter.ofdconverter.TextConverter;
import org.ofdrw.graphics2d.OFDGraphicsDocument;
import org.ofdrw.graphics2d.OFDPageGraphics2D;
import org.ofdrw.layout.PageLayout;
import org.ofdrw.pkg.tool.ElemCup;
import org.ofdrw.reader.OFDReader;
import com.gblfy.render.OFDRender;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;

/**
 * Title:     OFD格式转换
 * Description:
 * Date：     2024-06-11
 * Company:
 * @author
 * @version 1.0
 * ODF主要用于文本和表格文档（如ODT和ODS）
 * 导出：OFD文档导出为其它类型文档或媒体文件格式，如OFD导出为图片、文本、PDF等。
 * 转换：它类型文档或媒体文件格式转换为OFD文档，如PDF转换OFD、文本转换OFD等。
 */

public class OfdUtil {

    /**
     * 将ofd转换为pdf
     * @param originPath 源文件路径
     * @param pdfPath 目标文件路径
     * 不推荐导出为PDF，OFD本身就是国产的板式文件，
     * 非特殊场景没有必要导出为PDF文件，该模块将进入LTS状态，不再持续更新！
     * 导出无法保证文档效果一致性
     */
    public static boolean ofdToPdf(String originPath, String pdfPath) {
        Path src = Paths.get(originPath);
        Path dst = Paths.get(pdfPath);
        try {
            ConvertHelper.toPdf(src, dst);
            return true;
        } catch (GeneralConvertException e) {
            LogUtil.getLog(OfdUtil.class).error(e);
        }
        return false;
    }

    /**
     * 将ofd转换为HTML, 不成功,会报渲染错误
     * @param originPath 源文件路径
     * @param htmlPath 目标文件路径
     */
    public static boolean ofdToHtml(String originPath, String htmlPath)  {
        Path ofdIn = Paths.get(originPath);
        Path htmlOut = Paths.get(htmlPath);
        File originalFile = new File(originPath);
        File convertedFile = new File(htmlPath);

        try {
            HTMLExporter exporter = new HTMLExporter(ofdIn, htmlOut);
            exporter.export();

            // 获取文件大小
            long originalSize = originalFile.length();
            long convertedSize = convertedFile.length();

            // 检查文件大小是否远小于原始文件
            if (convertedSize < originalSize * 0.001) {
                System.err.println("文件生成失败！");
                convertedFile.delete();
                return false;
            }

            return true;
        } catch (IOException e) {
            LogUtil.getLog(OfdUtil.class).error(e);
        }
        return false;
    }

    /**
     * 将ofd转换为HTML 2,不成功,会报渲染错误
     * @param originPath 源文件路径
     * @param htmlPath 目标文件路径
     */
    public static boolean ofdToHtml2(String originPath, String htmlPath) {
        try {
            Path ofdIn = Paths.get(originPath);
            Path htmlOut = Paths.get(htmlPath);
            //[可选]配置字体，别名，扫描目录等
            // FontLoader.getInstance().addAliasMapping(null, "小标宋体", "方正小标宋简体", "方正小标宋简体")
            // FontLoader.getInstance().scanFontDir(new File("src/test/resources/fonts"));
            //配置参数（HTML页面宽度(px)），转换并存储HTML到文件。
            ConvertHelper.toHtml(ofdIn, htmlOut, 1000);
            return true;
        } catch (GeneralConvertException | IOException e) {
            LogUtil.getLog(OfdUtil.class).error(e);
        }
        return false;
    }

    /**
     * 将ofd转换为Txt
     * @param originPath 源文件路径
     * @param txtPath 目标文件路径
     */
    public static boolean ofdToTxt(String originPath, String txtPath) {
        Path ofdIn = Paths.get(originPath);
        Path txtOut = Paths.get(txtPath);
        try {
            TextExporter exporter = new TextExporter(ofdIn, txtOut);
            exporter.export();
            return true;
        } catch (IOException e) {
            LogUtil.getLog(OfdUtil.class).error(e);
        }
        return false;
    }

    /** 按页数转换
     * 将ofd转换为图片
     * @param originPath 源文件路径
     * @param imgPath 目标文件路径
     * 目前支持PNG、JPG、BPM，默认为PNG格式
     * 导出图片的质量，ppm参数，默认ppm为15
     */
    public static boolean ofdToImg(String originPath, String imgPath) {
        Path ofdPath = Paths.get(originPath);
        Path imgDirPath = Paths.get(imgPath);
        try {
            ImageExporter exporter = new ImageExporter(ofdPath, imgDirPath, "PNG", 20d);
            exporter.export();
            return true;
        } catch (IOException e) {
            LogUtil.getLog(OfdUtil.class).error(e);
        }
        return false;
    }

    /**
     * 将ofd转换为图片
     * @param originPath 源文件路径
     * @param imgPath 目标文件路径
     * @param type 文件后缀 目前支持PNG、JPG、BPM，默认为PNG格式
     * @param ppm 导出图片的质量，ppm参数，默认ppm为15
     */
    public static boolean ofdToImg(String originPath, String imgPath,String type,double ppm) {
        Path ofdPath = Paths.get(originPath);
        Path imgDirPath = Paths.get(imgPath);
        try {
            ImageExporter exporter = new ImageExporter(ofdPath, imgDirPath, type, ppm);
            exporter.export();
            return true;
        } catch (IOException e) {
            LogUtil.getLog(OfdUtil.class).error(e);
        }
        return false;
    }

    /** 测试未通过
     * 将ofd转换为图片
     * @param originPath 源文件路径
     * @param imgPath 目标文件路径
     * 目前支持PNG、JPG、BPM，默认为PNG格式
     * 导出图片的质量，ppm参数，默认ppm为15
     */
//    public static boolean ofdToImg2(String originPath, String imgPath) {
//        Path src = Paths.get(originPath);
//        //加载指定目录字体(非必须)
//        // FontLoader.getInstance().scanFontDir(new File("src/test/resources/fonts"));
//        //创建转换转换对象，设置 每毫米像素数量(Pixels per millimeter)
//        try(OFDReader reader = new OFDReader(src)) {
//            ImageMaker imageMaker = new ImageMaker(reader, 15);
//            for (int i = 0; i < imageMaker.pageSize(); i++) {
//                //指定页码转换图片
//                BufferedImage image = imageMaker.makePage(i);
//                Path dist = Paths.get("target", imgPath + "_" + i + ".png");
//                //存储为指定格式图片
//                ImageIO.write(image, "PNG", dist.toFile());
//            }
//            return true;
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//        return false;
//    }

    /** 未测试
     * 将ofd转换为SVG
     * @param originPath 源文件路径
     * @param svgPath 目标文件路径
     */
    public static boolean ofdToSvg(String originPath, String svgPath) {
        Path src = Paths.get(originPath);
        //载指定目录字体(非必须)
        // FontLoader.getInstance().scanFontDir(new File("src/test/resources/fonts"));
        //创建转换转换对象，设置 每毫米像素数量(Pixels per millimeter)
        try(OFDReader reader = new OFDReader(src)) {
            SVGMaker svgMaker = new SVGMaker(reader, 20d);
            for (int i = 0; i < svgMaker.pageSize(); i++) {
                //指定页码转换SVG，得到SVG(XML)
                String svg = svgMaker.makePage(i);
                Path dist = Paths.get("target", svgPath + "_" + i + ".svg");
                //存储到文件。
                Files.write(dist, svg.getBytes());
            }
            return true;
        } catch (IOException e) {
            LogUtil.getLog(OfdUtil.class).error(e);
        }
        return false;
    }

    /** 未成功
     * 将PDF转换为ofd
     * @param originPath 源文件路径
     * @param ofdPath 目标文件路径
     */
    public static boolean pdfToOfd(String originPath, String ofdPath) {
        Path src = Paths.get(originPath);
        Path dst = Paths.get(ofdPath);
        try(PDFConverter converter = new PDFConverter(dst)) {
            converter.convert(src);
            return true;
        } catch (IOException e) {
            LogUtil.getLog(OfdUtil.class).error(e);
        }
        return false;
    }

    /**
     * pdf转ofd
     *
     * @param originPath
     * @param ofdPath
     */

    public static boolean convertToOfdByStream(String originPath, String ofdPath) {

        Path input = Paths.get(originPath);
        Path output = Paths.get(ofdPath);
        for (int i = 0; i < 1; i++) {
            try {
                OFDRender.convertPdfToOfd(Files.newInputStream(input), Files.newOutputStream(output));
                return true;
            } catch (IOException e) {
                LogUtil.getLog(OfdUtil.class).error(e);
            }
        }
        return false;
    }

    /**
     * pdf转ofd
     *
     * @param originPath
     * @param ofdPath
     */
    public static boolean convertToOfd(String originPath, String ofdPath) {
        Path input = Paths.get(originPath);
        Path output = Paths.get(ofdPath);
        for (int i = 0; i < 1; i++) {
            try {
                byte[] pdfBytes = FileUtils.readFileToByteArray(input.toFile());
                byte[] ofdBytes = OFDRender.convertPdfToOfd(pdfBytes);
                if (Objects.nonNull(ofdBytes)) {
                    FileUtils.writeByteArrayToFile(output.toFile(), ofdBytes);
                    return true;
                } else {
                    LogUtil.getLog(OfdUtil.class).error("生成文档失败");
                    return false;
                }
            } catch (IOException e) {
                LogUtil.getLog(OfdUtil.class).error(e);
            }
        }
        return false;
    }

//    public static boolean pdfToOfd2(String pdfPath, String ofdPath) throws IOException {
//        PdfReader reader = new PdfReader(pdfPath);
//        FileOutputStream out = new FileOutputStream(ofdPath);
//        OfdWriter ofdWriter = new OfdWriter(out);
//        ofdWriter.setPdfReader(reader);
//        ofdWriter.convert();
//        ofdWriter.close();
//        reader.close();
//
//        return false;
//    }


    /** ofdrw 2.0.0版本低，用不了
     * 将PDF转换为ofd
     * @param originPath 源文件路径
     * @param ofdPath 目标文件路径
     * @param enableCopyAttachFiles 设置是否复制附件（默认复制）
     * @param enableCopyBookmarks 设置是否复制书签（默认复制）
     * @param UUPMM 设置毫米表示的用户单元数（PDF单位）
     */
//    public static boolean pdfToOfd(String originPath, String ofdPath,boolean enableCopyAttachFiles,boolean enableCopyBookmarks,double UUPMM) {
//        Path src = Paths.get(originPath);
//        Path dst = Paths.get(ofdPath);
//        try {
//            PDFConverter converter = new PDFConverter(dst);
//            converter.setEnableCopyAttachFiles(enableCopyAttachFiles);//设置是否复制附件（默认复制）
//            converter.setEnableCopyBookmarks(enableCopyBookmarks);//设置是否复制书签（默认复制）
//            converter.setUUPMM(UUPMM);//设置毫米表示的用户单元数（PDF单位）
//            converter.convert(src);
//            System.out.println(">> " + dst.toAbsolutePath());
//            return true;
//        } catch (IOException e) {
//            LogUtil.getLog(OfdUtil.class).error(e);
//        }
//        return false;
//    }

    /** 未测试
     * 将图片转换为ofd
     * @param originPath 源文件路径
     * @param ofdPath 目标文件路径
     */
    public static boolean imgToOfd(String originPath, String ofdPath) {
        Path src = Paths.get(originPath);
        Path dst = Paths.get(ofdPath);
        try {
            ImageConverter converter = new ImageConverter(dst);

            converter.convert(src);
            return true;
        } catch (IOException e) {
            LogUtil.getLog(OfdUtil.class).error(e);
        }
        return false;
    }

    /** 未测试
     * 将图片转换为ofd
     * @param originPath 源文件路径
     * @param ofdPath 目标文件路径
     * @param ppm 设置图片质量，单位为：每毫米像素数量
     * @param filepath,width，height 追加图片到新页面并指定显示大小
     * @param pageLayout 置OFD页面尺寸
     */
    public static boolean imgToOfd(String originPath, String ofdPath,double ppm,Path filepath, double width, double height,PageLayout pageLayout) {
        Path src = Paths.get(originPath);
        Path dst = Paths.get(ofdPath);
        try {
            ImageConverter converter = new ImageConverter(dst);
            converter.setPPM(ppm);
            converter.append(filepath,width,height);
            converter.setPageSize(pageLayout);
            converter.convert(src);
            LogUtil.getLog(OfdUtil.class).info(">> " + dst.toAbsolutePath());
            return true;
        } catch (IOException e) {
            LogUtil.getLog(OfdUtil.class).error(e);
        }
        return false;
    }

    /** 未成功
     * 将文本转换为ofd
     * @param originPath 源文件路径
     * @param ofdPath 目标文件路径
     */
    public static boolean txtToOfd(String originPath, String ofdPath) {
        Path src = Paths.get(originPath);
        Path dst = Paths.get(ofdPath);
        try(TextConverter converter = new TextConverter(dst);) {

            converter.convert(src);
            return true;
        } catch (IOException e) {
            LogUtil.getLog(OfdUtil.class).error(e);
        }
        return false;
    }

    /** 未测试
     * 将文本转换为ofd
     * @param originPath 源文件路径
     * @param ofdPath 目标文件路径
     * @param txt 追加文本，文本将新起一行
     * @param pageLayout 设置OFD页面尺寸
     * @param fontSize 设置字号，单位毫米
     */
    public static boolean txtToOfd(String originPath, String ofdPath, String txt, PageLayout pageLayout,double fontSize) {
        Path src = Paths.get(originPath);
        Path dst = Paths.get(ofdPath);
        try {
            TextConverter converter = new TextConverter(dst);
            converter.append(txt);//追加文本，文本将新起一行
            converter.setPageSize(pageLayout);//设置OFD页面尺寸
            converter.setFontSize(fontSize);//设置字号，单位毫米
            converter.convert(src);
            return true;
        } catch (IOException e) {
            LogUtil.getLog(OfdUtil.class).error(e);
        }
        return false;
    }

    /**
     * 删除 docx后 联动删 ofd格式文件
     *
     * @param filepath
     */
    public static void delOfd(String filepath) {
        String ofdfile = filepath.substring(0, filepath.lastIndexOf(".")) + ".ofd";

        File ofdFile = new File(ofdfile);
        if (ofdFile.exists()) {
            if (ofdFile.isFile()) {
                ofdFile.delete();
            }
        }
    }

    /**
     * 附件删除后，预览文件对应删除
     *
     * @param filepath
     */
    public static void delPreview(String filepath) {
        String htmlfile = filepath.substring(0, filepath.lastIndexOf(".")) + ".html";
        String imagesDir = filepath.substring(0, filepath.lastIndexOf(".")) + ".files";
        File htmlFile = new File(htmlfile);
        if (htmlFile.exists()) {
            if (htmlFile.isFile()) {
                htmlFile.delete();
            }
        }

        File f = new File(imagesDir);
        if (f.exists()) {
            fileDelete(f);
        }
    }

    /**
     * 删除文件夹及其下子文件
     *
     * @param file
     */
    public static void fileDelete(File file) {
        if (!file.exists()) {
            return;
        }
        if (file.isFile()) {
            file.delete();
        } else {
            for (File f : file.listFiles()) {
                fileDelete(f);
            }
            file.delete();
        }
    }
//    public static void main(String[] args) throws IOException {
//        String originPath = "src/main/webapp/public/模板1.pdf";
//        String ofdPath = "src/main/webapp/public/模板6.ofd";
//        File inputFile = new File(originPath);
//        if (!inputFile.exists()) {
//            System.out.println(">>>>>>>> Office To PDF > 没有找到源文件!!");// 找不到源文件,
//            // 则返回false
//        }
//        //String ofdPath = "c-main/src/main/webapp/public/模板1.odf";
//        System.out.println(ofdPath);
//
//        boolean re = OfdUtil.pdfToOfd(originPath,ofdPath);
//        System.out.println(re);
//    }

//    public static void main(String[] args) throws IOException {
//        //String originPath = "src/main/webapp/public/某某文件.docx";
//        //String originPath = "d:/a.pdf";
//        //String originPath = "src/main/webapp/public/Java开发手册(黄山版)2026.ofd";
//        //String originPath = "src/main/webapp/public/模板2xlsx.xlsx";
//        //String originPath = "src/main/webapp/public/模板1.ofd";
//        // String originPath = "D:/home8.0/upfile/file_flow/2024/7/1720167366839984566041.ofd";
//        String originPath = "D:/home8.0/upfile/file_flow/2024/7/17204146380552105739578.pdf";
//
//        //String originPath = "src/main/webapp/public/Java开发手册(黄山版)2026.ofd";
//
//        //String ofdPath = "src/main/webapp/public/模板111.ofd";
//        //String ofdPath = "src/main/webapp/public/模板1.pdf";
//        //String ofdPath = "src/main/webapp/public/模板123456.html";
//        String ofdPath = "D:/home8.0/upfile/file_flow/2024/7/1.ofd";
//        //String ofdPath = "src/main/webapp/public/Java开发手册(黄山版)2026_2024.html";
//        //String ofdPath = "src/main/webapp/public/Java开发手册(黄山版)2022转.pdf";
//        //String ofdPath = "src/main/webapp/public/Java开发手册(黄山版)2026_0";
//        //String ofdPath = "src/main/webapp/public/南京投资促进管理系统 安全报告63.ofd";
////        String ofdPath = "src/main/webapp/public/某某文件.pdf";
//        //String ofdPath = "src/main/webapp/public/模板2xlsx.ofd";
//        File inputFile = new File(originPath);
//        if (!inputFile.exists()) {
//            System.out.println(">>>>>>>> Office To PDF > 没有找到源文件!!");// 找不到源文件,
//            // 则返回false
//        }
//        //String ofdPath = "c-main/src/main/webapp/public/模板1.odf";
//        System.out.println(ofdPath);
//
//        // OFD To PDF OK 不过有些小瑕疵
//        //boolean re = OfdUtil.ofdToPdf(originPath,ofdPath);
//        //boolean re = OfdUtil.ofdToHtml(originPath,ofdPath);
//        //boolean re = OfdUtil.ofdToTxt(originPath,ofdPath);
//        //boolean re = OfdUtil.ofdToImg(originPath,ofdPath);
//        //boolean re = OfdUtil.ofdToImg(originPath,ofdPath,"jpg",20);
//        //boolean re = OfdUtil.ofdToImg2(originPath,ofdPath);
//        //boolean re = OfdUtil.ofdToSvg(originPath,ofdPath);
//        //boolean re = OfdUtil.pdfToOfd(originPath,ofdPath);
//        //boolean re = OfdUtil.pdfToOfd(originPath,ofdPath);
//        boolean re = OfdUtil.convertToOfdByStream(originPath,ofdPath);
//
//
////        boolean re = OfdUtil.convertToOfd(originPath,ofdPath);
//        //boolean re = OfdUtil.xlsxToOfd(originPath,ofdPath);
//
//
//    }
}
